package com.tengju.bff.interfaces.covercharge.util.alarmUtil;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.StringTokenizer;

/**
 * IpUtils
 *
 * @author Giles.wu
 * @date 2016/10/11 11:28
 */
public class IpUtils {

    private static final Logger LOG = LoggerFactory.getLogger(IpUtils.class);

    static final String DEF_IP = "127.0.0.1";

    static String localIp = null;
    static String localV4Ips = null;
    static String localUserName = null;

    static final String UNKNOWN = "unknown";

    private IpUtils() {
    }

    /**
     * 获取请求的客户端的IP地址
     *
     * @param request
     * @return
     */
    public static String getIpAddr(HttpServletRequest request) {
        //X-Forwarded-For  x-forwarded-for
        String ipAddress = request.getHeader("x-forwarded-for");
        if (StringUtils.isEmpty(ipAddress) || UNKNOWN.equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("X-Real-IP");
        }
        if (StringUtils.isEmpty(ipAddress) || UNKNOWN.equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("Proxy-Client-IP");
        }
        if (StringUtils.isEmpty(ipAddress) || UNKNOWN.equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("WL-Proxy-Client-IP");
        }
        if (StringUtils.isEmpty(ipAddress) || UNKNOWN.equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getRemoteAddr();
            if (DEF_IP.equals(ipAddress) || "0:0:0:0:0:0:0:1".equals(ipAddress)) {
                ipAddress = getLocalNetWorkIp();
            }
        }
        // 对于通过多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割 // "***.***.***.***".length()
        if (ipAddress != null && ipAddress.length() > 15) {
            char indexFix = ',';
            int lenFix = ipAddress.indexOf(indexFix);
            if (lenFix > 0) {
                ipAddress = ipAddress.substring(0, lenFix);
            }
        }
        return ipAddress;
    }


    /**
     * 获取请求的客户端的IP地址的列表
     *
     * @param request
     * @return
     */
    public static List<String> getIpAddrList(HttpServletRequest request) {
        //X-Forwarded-For  x-forwarded-for
        String ipAddress = request.getHeader("x-forwarded-for");
        if (StringUtils.isEmpty(ipAddress) || UNKNOWN.equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("X-Real-IP");
        }
        if (StringUtils.isEmpty(ipAddress) || UNKNOWN.equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("Proxy-Client-IP");
        }
        if (StringUtils.isEmpty(ipAddress) || UNKNOWN.equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("WL-Proxy-Client-IP");
        }
        if (StringUtils.isEmpty(ipAddress) || UNKNOWN.equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getRemoteAddr();
            if (DEF_IP.equals(ipAddress) || "0:0:0:0:0:0:0:1".equals(ipAddress)) {
                ipAddress = getLocalNetWorkIp();
            }
        }

        List ipAddressList = new ArrayList();
        // 对于通过多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割 // "***.***.***.***".length()
        if (ipAddress != null && ipAddress.length() > 15) {
            char indexFix = ',';
            int lenFix = ipAddress.indexOf(indexFix);
            if (lenFix > 0) {
                final String[] split = ipAddress.split(",");
                for (String s : split) {
                    ipAddressList.add(s.trim());
                }
            }
        } else if (ipAddress != null) {
            ipAddressList.add(ipAddress);
        }

        return ipAddressList;
    }

    /**
     * 获取本机的网络IP
     */
    public static String getLocalNetWorkIp() {
        if (localIp != null) {
            return localIp;
        }
        try {
            Enumeration<NetworkInterface> netInterfaces = NetworkInterface.getNetworkInterfaces();
            // 遍历所有的网卡
            while (netInterfaces.hasMoreElements()) {
                NetworkInterface ni = netInterfaces.nextElement();
                // 如果是回环和虚拟网络地址的话继续
                if (ni.isLoopback() || ni.isVirtual()) {
                    continue;
                }
                Enumeration<InetAddress> addresss = ni.getInetAddresses();
                while (addresss.hasMoreElements()) {
                    InetAddress address = addresss.nextElement();
                    if (address instanceof Inet4Address) {
                        // 这里暂时只获取ipv4地址
                        localIp = address.getHostAddress();
                        return localIp;
                    }
                }
            }
            localIp = DEF_IP;
        } catch (Exception e) {
            localIp = DEF_IP;
        }
        return localIp;
    }

    /**
     * 获取本机的所有网络IP
     */
    public static String getLocalNetWorkV4Ips() {
        if (localV4Ips != null) {
            return localV4Ips;
        }

        try {
            Enumeration<NetworkInterface> netInterfaces = NetworkInterface.getNetworkInterfaces();
            List<String> v4Ips = new ArrayList<>();
            List<String> hostNames = new ArrayList<>();

            // 遍历所有的网卡
            while (netInterfaces.hasMoreElements()) {
                NetworkInterface ni = netInterfaces.nextElement();
                // 如果是回环和虚拟网络地址的话继续
                if (ni.isLoopback() || ni.isVirtual()) {
                    continue;
                }
                Enumeration<InetAddress> addresss = ni.getInetAddresses();
                while (addresss.hasMoreElements()) {
                    InetAddress address = addresss.nextElement();
                    // 这里暂时只获取ipv4地址
                    if (address instanceof Inet4Address) {
                        v4Ips.add(address.getHostAddress());
                        if (!v4Ips.contains(address.getHostName()) && !hostNames.contains(address.getHostName())) {
                            hostNames.add(address.getHostName());
                        }
                    }
                }
            }
            if (!v4Ips.isEmpty()) {
                localV4Ips = StringUtils.join(v4Ips.toArray(), ",");
                localUserName = StringUtils.join(hostNames.toArray(), ",");
            }
        } catch (Exception e) {
            LOG.error("get ip error:{}", e.getMessage());
        } finally {
            if (localV4Ips == null) {
                localV4Ips = DEF_IP;
            }
            if (localUserName == null) {
                localUserName = "HostName";
            }
            localUserName += " - : " + System.getProperties().getProperty("user.name");
        }
        return localV4Ips;
    }

    /**
     * 获取 localName
     *
     * @return
     */
    public static String getLocalUserNames() {
        getLocalNetWorkV4Ips();
        return localUserName;
    }

    /**
     * 客户端上送的ip无效时，设置一个固定ip
     *
     * @param tempIp
     * @return
     */
    public static String getClientIp(String tempIp) {
        return (StringUtils.isEmpty(tempIp) || "error".equals(tempIp) || !isIpValid(tempIp)) ? DEF_IP : tempIp;
    }

    /**
     * 校验Ip地址是否合法
     *
     * @param addr
     * @return
     */
    public static boolean isIpValid(String addr) {
        try {
            String[] ipStr = new String[4];
            int[] ipb = new int[4];
            StringTokenizer tokenizer = new StringTokenizer(addr, ".");
            int len = tokenizer.countTokens();

            if (len != 4) {
                return false;
            }
            int i = 0;
            while (tokenizer.hasMoreTokens()) {
                ipStr[i] = tokenizer.nextToken();
                ipb[i] = (new Integer(ipStr[i])).intValue();

                if (ipb[i] < 0 || ipb[i] > 255) {
                    return false;
                }
                i++;
            }
            return (ipb[0] > 0);
        } catch (Exception e) {
            return false;
        }
    }

    public static void main(String[] args) {
        LOG.info(getLocalUserNames());
    }

}
